﻿using Caliburn.Micro;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace AdornerTest
{
	/// <summary>
	/// This is (for simplicity sake) acting as the ViewModel and the View
	/// </summary>
	public partial class MainWindow : Window, INotifyPropertyChanged
	{

		/// <summary>
		/// The collection of all contenxt menu items for the main canvas
		/// </summary>
		public ObservableCollection<SomeContextMenuItem> ContextItems { get; set; }



		private SomeItem _selectedItem = null;
		/// <summary>
		///  the currently selected SomeItem
		/// </summary>
		public SomeItem SelectedItem
		{
			get { return _selectedItem; }
			set
			{
				if (_selectedItem != value)
				{
					_selectedItem = value;
					this.NotifyOfPropertyChange("SelectedItem");
				}
			}
		}

		public MainWindow()
		{
			InitializeComponent();
			this.AllItems = new ObservableCollection<SomeItem>();
			this.Loaded += MainWindow_Loaded;
			this.DataContext = this;
			this.ContextItems = new ObservableCollection<SomeContextMenuItem>();
			this.ContextItems.Add(new SomeContextMenuItem() { Name = "Paste", Action = new PasteItemCommand() });
			this.PreviewMouseDown += MainWindow_PreviewMouseDown;
			// Add some sample data
			AddItem(ItemType.Input);
			AddItem(ItemType.Output);
		}

		/// <summary>
		/// Deselect any selected items if you click on the canvas
		/// </summary>
		private void MainWindow_PreviewMouseDown(object sender, MouseButtonEventArgs e)
		{
			//TODO: this needs work to deselect any items if canvas is clicked
			foreach (var a in this.AllItems.Where(x => x.IsSelected))
			{
				a.IsSelected = false;
			}
			
		}
		AdornerLayer _mainAdorner = null;
		private void MainWindow_Loaded(object sender, RoutedEventArgs e)
		{
			Console.WriteLine(this.itms.Items.Count.ToString());
			//_mainAdorner = AdornerLayer.GetAdornerLayer(this.itms);

			//_mainAdorner.Add(new PinAdorner(this.itms));
		}

		/// <summary>
		/// Collection of all SomeItems on the canvas
		/// </summary>
		public ObservableCollection<SomeItem> AllItems
		{
			get; set;
		}

		/// <summary>
		/// When you click on an item in the canvas, put an adorner around it 
		/// that allows you to move the item around
		/// </summary>
		private void someItem_MouseDown(object sender, MouseButtonEventArgs e)
		{
			try
			{
				//TODO: Move this logic to the change of IsSelected...
				// not sure if that would violate MVVM.. hmmm
				FrameworkElement r = sender as FrameworkElement;
				var myAdornerLayer = AdornerLayer.GetAdornerLayer(r);
				if (myAdornerLayer != null)
				{
					var ads = myAdornerLayer.GetAdorners(sender as FrameworkElement);
					if (ads != null && ads.Count() > 0)
					{
						foreach (Adorner a in ads)
						{
							myAdornerLayer.Remove(a);
						}
						(r.DataContext as SomeItem).IsSelected = false;
					}
					else
					{
						myAdornerLayer.Add(new SimpleCircleAdorner(sender as FrameworkElement));
						(r.DataContext as SomeItem).IsSelected = true;
						this.SelectedItem = (r.DataContext as SomeItem);
					}


				}
			}
			catch (Exception EX)
			{
				Console.WriteLine(EX.Message);
			}
		}

		private void someItem_MouseUp(object sender, MouseButtonEventArgs e)
		{

		}

		#region NOTIFY PROPERTY CHANGED
		public event PropertyChangedEventHandler PropertyChanged;

		private void NotifyOfPropertyChange(string name)
		{
			PropertyChangedEventHandler pc = this.PropertyChanged;
			if (pc != null)
			{
				pc(this, new PropertyChangedEventArgs(name));
			}
		}
		#endregion

		/// <summary>
		/// Add a new item to the canvas
		/// </summary>
		private void btnAddInput_Click(object sender, RoutedEventArgs e)
		{
			AddItem(ItemType.Input);

		}

		/// <summary>
		/// Add an item of type ItemType
		/// </summary>
		/// <param name="itemType"></param>
		private void AddItem(ItemType itemType)
		{
			//Move the next added item a little away so they dont stack up
			double p = 30 + (10 * this.AllItems.Count);
			switch (itemType)
			{
				case ItemType.Input:
					SomeItem i = new SomeItem(p, p, 200, 150, "Item" + this.AllItems.Count.ToString(), Brushes.Blue) { IsInput = true };
					
					this.AllItems.Add(i);
					break;
				case ItemType.Output:
					this.AllItems.Add(new SomeItem(p, p, 200, 150, "Item" + this.AllItems.Count.ToString(), Brushes.Green) { IsOutput = true });
					break;
				default:
					break;
			}
		}


		/// <summary>
		/// Add a new item to the canvas
		/// </summary>
		private void btnAddOutput_Click(object sender, RoutedEventArgs e)
		{
			AddItem(ItemType.Output);
		}

		/// <summary>
		/// Starting to get item connector lines ... not working yet
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <returns></returns>
		//private void Thumb_DragDelta(object sender, DragDeltaEventArgs e)
		//{
		//	Thumb t = sender as Thumb;
		//	if(t != null)
		//	{
		//		var rubberAdorner = AdornerLayer.GetAdornerLayer(t);
		//		Canvas foundCanvas = FindChild<Canvas>(Application.Current.MainWindow, "mainCanvas");
		//		if (t.Tag is Line)
		//		{
		//			Line l = t.Tag as Line;
		//			l.X1 = 0;// (double)t.GetValue(Canvas.LeftProperty);
		//			l.Y1 = 0;// (double)t.GetValue(Canvas.TopProperty);
		//			l.X2 = l.X1 + e.HorizontalChange;
		//			l.Y2 = l.Y1 + e.VerticalChange;

		//		}
		//		else
		//		{
		//			Line l = new Line();
		//			l.X1 = 0;// (double)t.GetValue(Canvas.LeftProperty);
		//			l.Y1 = 0;// (double)t.GetValue(Canvas.TopProperty);
		//			l.X2 = l.X1 + e.HorizontalChange;
		//			l.Y2 = l.Y1 + e.VerticalChange;
		//			t.Tag = l;
		//			foundCanvas.Children.Add(l);
		//		}
		//	}
		//}

		//private void Thumb_DragStarted(object sender, DragStartedEventArgs e)
		//{

		//}

		public static T FindChild<T>(DependencyObject parent, string childName)
   where T : DependencyObject
		{
			// Confirm parent and childName are valid. 
			if (parent == null) return null;

			T foundChild = null;

			int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
			for (int i = 0; i < childrenCount; i++)
			{
				var child = VisualTreeHelper.GetChild(parent, i);
				// If the child is not of the request child type child
				T childType = child as T;
				if (childType == null)
				{
					// recursively drill down the tree
					foundChild = FindChild<T>(child, childName);

					// If the child is found, break so we do not overwrite the found child. 
					if (foundChild != null) break;
				}
				else if (!string.IsNullOrEmpty(childName))
				{
					var frameworkElement = child as FrameworkElement;
					// If the child's name is set for search
					if (frameworkElement != null && frameworkElement.Name == childName)
					{
						// if the child's name is of the request name
						foundChild = (T)child;
						break;
					}
				}
				else
				{
					// child element found.
					foundChild = (T)child;
					break;
				}
			}

			return foundChild;
		}

		private void Border_Loaded(object sender, RoutedEventArgs e)
		{
			FrameworkElement r = sender as FrameworkElement;
			var myAdornerLayer = AdornerLayer.GetAdornerLayer(r);
			if (myAdornerLayer != null)
			{

				myAdornerLayer.Add(new PinAdorner(sender as FrameworkElement));
				
			}
		}
	}



}
